<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/601748 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <meta name="content-class" content="yinxiang.markdown"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="1035"/>

<div><span><div style="font-size: 14px; margin: 0; padding: 0; width: 100%;"><h2 style="line-height: 160%; box-sizing: content-box; font-weight: 700; font-size: 34px; border-bottom: 1px solid #dbdbdb; color: #333;">设计模式</h2>
<h3 style="line-height: 160%; box-sizing: content-box; font-weight: 700; font-size: 27px; color: #333;">策略模式</h3>
<h4 style="line-height: 160%; box-sizing: content-box; font-size: 20px; color: #333;">什么是策略模式</h4>
<ul style="line-height: 160%; box-sizing: content-box; display: block; list-style-type: disc; padding-left: 30px; margin: 6px 0 10px; color: #333;">
<li style="line-height: 160%; box-sizing: content-box; position: relative;">定义一系列算法，把它们一一封装起来，并且使它们可以互相替换，本模式使得算法可以独立于使用它的客户而变化</li>
</ul>
<h4 style="line-height: 160%; box-sizing: content-box; font-size: 20px; color: #333;">策略模式包含什么</h4>
<ul style="line-height: 160%; box-sizing: content-box; display: block; list-style-type: disc; padding-left: 30px; margin: 6px 0 10px; color: #333;">
<li style="line-height: 160%; box-sizing: content-box; position: relative;">1.上下文：把一些计算委托给实现不同算法的可互换组件，它提供服务</li>
<li style="line-height: 160%; box-sizing: content-box; position: relative;">2.策略：实现不同算法的组件共同的接口</li>
<li style="line-height: 160%; box-sizing: content-box; position: relative;">3.具体策略：“策略”的具体子类</li>
</ul>
<h4 style="line-height: 160%; box-sizing: content-box; font-size: 20px; color: #333;">电商系统例子（可参考Java的抽象类）</h4>
<blockquote style="line-height: 160%; box-sizing: content-box; margin: 15px 0; border-left: 4px solid #ddd; padding: 0 15px; color: #777;">
<p style="line-height: 160%; box-sizing: content-box; margin: 10px 0; color: #333; margin-top: 0;">假设一个网店定制了以下折扣规则</p>
<ul style="line-height: 160%; box-sizing: content-box; display: block; list-style-type: disc; padding-left: 30px; margin: 6px 0 10px; color: #333; margin-bottom: 0;">
<li style="line-height: 160%; box-sizing: content-box; position: relative;">有1000或以上积分的顾客，每个订单享5%的折扣</li>
<li style="line-height: 160%; box-sizing: content-box; position: relative;">同一订单中，单个商品的数量达到20个或以上，享10%的折扣</li>
<li style="line-height: 160%; box-sizing: content-box; position: relative;">订单中的不同商品达到10个或以上，享7%折扣</li>
</ul>
</blockquote>
<pre style="line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; margin: 2px 0 8px; background-color: #f5f7f8;"><code style="display: block; overflow-x: auto; background: #1e1e1e; line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; letter-spacing: -.3px; padding: 18px; color: #f4f4f4; white-space: pre-wrap;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">from</span> abc <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">import</span> ABC , abstracmethod
<span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">from</span> collections <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">import</span> namdtuple

Customer = namdtuple(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'Customer'</span>,<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'name fidelity'</span>)    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#客户名name 和积分数fidelity   namdtuple还要记得先传入类名</span>

<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">LineItem</span>:</span>    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#商品信息类</span>
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__init__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , product , quantity , price)</span>:</span>
        self.product = product   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#具体商品</span>
        self.quantity = quantity   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#数量</span>
        self.price = price             <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#单价</span>
        
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">total</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>     <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#总价</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.price * self.quantity
        
<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">Order</span>:</span>   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#上下文</span>
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__init__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , customer , cart , promotion = None)</span>:</span>   
        self.customer = customer   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#客户类</span>
        self.cart = list(cart)         <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#由具体商品信息组成的列表</span>
        self.promotion = promotion    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#具体的打折策略</span>
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">total</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">not</span> hasattr(self , <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'__total'</span>):    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#检查是否有__total这个属性</span>
            self.__total = sum(item.total() <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> self.cart)
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.__total
    
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">due</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> self.promotion <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">is</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">None</span>:
            discount = <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">else</span>:
            discount = self.promotion.discount(self)
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.total() - discount
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__repr__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        fmt = <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'&lt;Order total : { : .2f } due : { : .2f }&gt;'</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> fmt.format(self.total() , self.due())
        
        
<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">Promotion</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(ABC)</span>:</span>   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#策略，抽象基类</span>
<span style="color: #9b9b9b; line-height: 160%; box-sizing: content-box;">    @abstractmothod</span>
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">discount</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , other)</span>:</span>
        <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''返回折扣金额（正值）'''</span>      <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#抽象方法，只有方法，没有具体实现，专门设计为来被继承的</span>

<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">FidelityPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(Promotion)</span>:</span> <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第一个策略  都是Promotion的子类</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''为积分为1000或以上的顾客提供5%的折扣'''</span>
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">discount</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self . other)</span>:</span>   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#继承后覆写，完成具体功能实现</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> order.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.05</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> order.customer.fidelity &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">1000</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">else</span> <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
 
 
 <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">BulkItemPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(Promotion)</span>:</span>  <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第二个策略</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''单个商品为20个或以上时提供10%的折扣'''</span>
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">discount</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , other )</span>:</span>
        discount = <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> order.cart:
            <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> item.quantity &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">20</span>:
                discount += item.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.1</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> discount
 
 <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">LargeOrderPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(Promotion)</span>:</span>  <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第三个策略</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''订单中的不同商品达到10个或以上时提供7%的折扣'''</span>
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">discount</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self, order)</span>:</span>
        distinct_items = {item.product <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> order.cart}
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> len(distinct_items) &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">10</span>:
            <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> order.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.07</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
    
</code></pre>
<pre style="line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; margin: 2px 0 8px; background-color: #f5f7f8;"><code style="display: block; overflow-x: auto; background: #1e1e1e; line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; letter-spacing: -.3px; padding: 18px; color: #f4f4f4; white-space: pre-wrap;">joe = Customer(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'John doe'</span> , <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>)
ann = Customer(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'Ann Smith'</span> , <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">1100</span> )
cart = [LineItem(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'banana'</span>, <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">4</span>, <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.5</span>),
          LineItem(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'Apple'</span> , <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">10</span> , <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">1.5</span>),
          LineItem(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'watermellon'</span>, <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">5</span>, <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">5.0</span>)]
Order(joe, cart , FidelityPromo() )      <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;"># &lt;Order total : 42.00 due : 42.00&gt;</span>
Order(ann , cart , FidelityPromo() )      <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;"># &lt;Order total : 42.00 due : 39.00&gt;</span>

</code></pre>
<h4 style="line-height: 160%; box-sizing: content-box; font-size: 20px; color: #333;">使用函数实现“策略”模式</h4>
<pre style="line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; margin: 2px 0 8px; background-color: #f5f7f8;"><code style="display: block; overflow-x: auto; background: #1e1e1e; line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; letter-spacing: -.3px; padding: 18px; color: #f4f4f4; white-space: pre-wrap;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">from</span> abc <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">import</span> ABC , abstracmethod
<span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">from</span> collections <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">import</span> namdtuple

Customer = namdtuple(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'Customer'</span>,<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'name fidelity'</span>)    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#客户名name 和积分数fidelity   namdtuple还要记得先传入类名</span>

<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">LineItem</span>:</span>    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#商品信息类</span>
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__init__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , product , quantity , price)</span>:</span>
        self.product = product   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#具体商品</span>
        self.quantity = quantity   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#数量</span>
        self.price = price             <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#单价</span>
        
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">total</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>     <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#总价</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.price * self.quantity
        
<span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">class</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">Order</span>:</span>   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#上下文</span>
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__init__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self , customer , cart , promotion = None)</span>:</span>   
        self.customer = customer   <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#客户类</span>
        self.cart = list(cart)         <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#由具体商品信息组成的列表</span>
        self.promotion = promotion    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#具体的打折策略</span>
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">total</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">not</span> hasattr(self , <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'__total'</span>):    <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#检查是否有__total这个属性</span>
            self.__total = sum(item.total() <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> self.cart)
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.__total
    
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">due</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> self.promotion <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">is</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">None</span>:
            discount = <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">else</span>:
        
            <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#差别  重点</span>
            discount = self.promotion(self)     <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#调用self.promotion函数 ， 传入当前实例,  self.&lt;&gt;(self)</span>
            
            
            
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> self.total() - discount
    
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">__repr__</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(self)</span>:</span>
        fmt = <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'&lt;Order total : { : .2f } due : { : .2f }&gt;'</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> fmt.format(self.total() , self.due())
        
<span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#不用抽象类了</span>
<span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">fidelityPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(order)</span>:</span> <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第一个策略  </span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''为积分为1000或以上的顾客提供5%的折扣'''</span>
    <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> order.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.05</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> order.customer.fidelity &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">1000</span> <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">else</span> <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
 
 
<span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">bulkItemPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(order)</span>:</span>  <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第二个策略</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''单个商品为20个或以上时提供10%的折扣'''</span>
        discount = <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> order.cart:
            <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> item.quantity &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">20</span>:
                discount += item.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.1</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> discount
 
 <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">largeOrderPromo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(order)</span>:</span>  <span style="color: #57a64a; font-style: italic; line-height: 160%; box-sizing: content-box;">#第三个策略</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''订单中的不同商品达到10个或以上时提供7%的折扣'''</span>
        distinct_items = {item.product <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> item <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> order.cart}
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> len(distinct_items) &gt;= <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">10</span>:
            <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> order.total() * <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">.07</span>
        <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> <span style="color: #b8d7a3; line-height: 160%; box-sizing: content-box;">0</span>
</code></pre>
<blockquote style="line-height: 160%; box-sizing: content-box; margin: 15px 0; border-left: 4px solid #ddd; padding: 0 15px; color: #777;">
<p style="line-height: 160%; box-sizing: content-box; margin: 10px 0; color: #333; margin-top: 0; margin-bottom: 0;"><strong style="line-height: 160%; box-sizing: content-box; font-weight: 700;">策略对象通常是很好的享元（可共享的对象，可以同时在多个上下文中使用，共享是推荐的做法，这样可以不用再每个新的上下文中使用相同的策略时不断新建具体策略对象，从而减少消耗）。</strong><br/>
<strong style="line-height: 160%; box-sizing: content-box; font-weight: 700;">具体策略一般没有内部状态，只是处理上下文中的数据，所以复杂情况下，一定要用函数实现“策略”模式，函数比用户定义的类的实例更轻量，而且无需使用享元模式，因为各个策略函数在Python编译模块时只会创建一次。普通的函数也是“可共享的对象”，可以同时在多个上下文中使用。</strong></p>
</blockquote>
<h4 style="line-height: 160%; box-sizing: content-box; font-size: 20px; color: #333;">选择最佳策略：简单的方式</h4>
<pre style="line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; margin: 2px 0 8px; background-color: #f5f7f8;"><code style="display: block; overflow-x: auto; background: #1e1e1e; line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; letter-spacing: -.3px; padding: 18px; color: #f4f4f4; white-space: pre-wrap;">promos = [fidelity_promo , bulk_item_promo , large_oder_promo]

<span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">best_promo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(order)</span>:</span>
    <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'''
        使用生成器表达式把order传给promos列表中的各个函数，返回折扣额度最大的那个函数
    '''</span>
    <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> max(promo(order) <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> promo <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> promos)       
    
</code></pre>
<p style="line-height: 160%; box-sizing: content-box; margin: 10px 0; color: #333;"><strong style="line-height: 160%; box-sizing: content-box; font-weight: 700;">不足：如果添加了新的销售策略，要定义相应的函数，还得记得把新函数添加到promos中，否则best_promos不会考虑它</strong></p>
<p style="line-height: 160%; box-sizing: content-box; margin: 10px 0; color: #333;"><strong style="line-height: 160%; box-sizing: content-box; font-weight: 700;">改进：使用处理模块的函数，找出模块中的全部策略</strong></p>
<blockquote style="line-height: 160%; box-sizing: content-box; margin: 15px 0; border-left: 4px solid #ddd; padding: 0 15px; color: #777;">
<p style="line-height: 160%; box-sizing: content-box; margin: 10px 0; color: #333; margin-top: 0; margin-bottom: 0;">globals() 返回一个字典，表示当前的全局符号表，这个符号表始终针对当前模块</p>
</blockquote>
<pre style="line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; margin: 2px 0 8px; background-color: #f5f7f8;"><code style="display: block; overflow-x: auto; background: #1e1e1e; line-height: 160%; box-sizing: content-box; border: 0; border-radius: 0; letter-spacing: -.3px; padding: 18px; color: #f4f4f4; white-space: pre-wrap;">    promos = [globals()[name] <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> name <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> globals()
                    <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">if</span> name.endwith(<span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'_promo'</span>)
                    <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">and</span> name != <span style="color: #d69d85; line-height: 160%; box-sizing: content-box;">'best_promo'</span>]
    <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;"><span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">def</span> <span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">best_promo</span><span style="color: #dcdcdc; line-height: 160%; box-sizing: content-box;">(order)</span>:</span>
         <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">return</span> max(promo(order) <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">for</span> promo <span style="color: #569cd6; line-height: 160%; box-sizing: content-box;">in</span> promos)
    
</code></pre>
<h3 style="line-height: 160%; box-sizing: content-box; font-weight: 700; font-size: 27px; color: #333;">命令模式</h3>
<ul style="line-height: 160%; box-sizing: content-box; display: block; list-style-type: disc; padding-left: 30px; margin: 6px 0 10px; color: #333;">
<li style="line-height: 160%; box-sizing: content-box; position: relative;">略</li>
</ul>
<h5 style="line-height: 160%; box-sizing: content-box; font-weight: 700; font-size: 16px; color: #333;">用装饰器也可以解决电商问题，未完待续</h5>
</div><center style="display:none !important;visibility:collapse !important;height:0 !important;white-space:nowrap;width:100%;overflow:hidden">%23%23%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%0A%23%23%23%20%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%0A%23%23%23%23%20%E4%BB%80%E4%B9%88%E6%98%AF%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%0A-%20%E5%AE%9A%E4%B9%89%E4%B8%80%E7%B3%BB%E5%88%97%E7%AE%97%E6%B3%95%EF%BC%8C%E6%8A%8A%E5%AE%83%E4%BB%AC%E4%B8%80%E4%B8%80%E5%B0%81%E8%A3%85%E8%B5%B7%E6%9D%A5%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BD%BF%E5%AE%83%E4%BB%AC%E5%8F%AF%E4%BB%A5%E4%BA%92%E7%9B%B8%E6%9B%BF%E6%8D%A2%EF%BC%8C%E6%9C%AC%E6%A8%A1%E5%BC%8F%E4%BD%BF%E5%BE%97%E7%AE%97%E6%B3%95%E5%8F%AF%E4%BB%A5%E7%8B%AC%E7%AB%8B%E4%BA%8E%E4%BD%BF%E7%94%A8%E5%AE%83%E7%9A%84%E5%AE%A2%E6%88%B7%E8%80%8C%E5%8F%98%E5%8C%96%0A%23%23%23%23%20%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E5%8C%85%E5%90%AB%E4%BB%80%E4%B9%88%0A-%201.%E4%B8%8A%E4%B8%8B%E6%96%87%EF%BC%9A%E6%8A%8A%E4%B8%80%E4%BA%9B%E8%AE%A1%E7%AE%97%E5%A7%94%E6%89%98%E7%BB%99%E5%AE%9E%E7%8E%B0%E4%B8%8D%E5%90%8C%E7%AE%97%E6%B3%95%E7%9A%84%E5%8F%AF%E4%BA%92%E6%8D%A2%E7%BB%84%E4%BB%B6%EF%BC%8C%E5%AE%83%E6%8F%90%E4%BE%9B%E6%9C%8D%E5%8A%A1%0A-%202.%E7%AD%96%E7%95%A5%EF%BC%9A%E5%AE%9E%E7%8E%B0%E4%B8%8D%E5%90%8C%E7%AE%97%E6%B3%95%E7%9A%84%E7%BB%84%E4%BB%B6%E5%85%B1%E5%90%8C%E7%9A%84%E6%8E%A5%E5%8F%A3%0A-%203.%E5%85%B7%E4%BD%93%E7%AD%96%E7%95%A5%EF%BC%9A%E2%80%9C%E7%AD%96%E7%95%A5%E2%80%9D%E7%9A%84%E5%85%B7%E4%BD%93%E5%AD%90%E7%B1%BB%0A%0A%23%23%23%23%20%E7%94%B5%E5%95%86%E7%B3%BB%E7%BB%9F%E4%BE%8B%E5%AD%90%EF%BC%88%E5%8F%AF%E5%8F%82%E8%80%83Java%E7%9A%84%E6%8A%BD%E8%B1%A1%E7%B1%BB%EF%BC%89%0A%3E%20%E5%81%87%E8%AE%BE%E4%B8%80%E4%B8%AA%E7%BD%91%E5%BA%97%E5%AE%9A%E5%88%B6%E4%BA%86%E4%BB%A5%E4%B8%8B%E6%8A%98%E6%89%A3%E8%A7%84%E5%88%99%0A%3E%20-%20%E6%9C%891000%E6%88%96%E4%BB%A5%E4%B8%8A%E7%A7%AF%E5%88%86%E7%9A%84%E9%A1%BE%E5%AE%A2%EF%BC%8C%E6%AF%8F%E4%B8%AA%E8%AE%A2%E5%8D%95%E4%BA%AB5%25%E7%9A%84%E6%8A%98%E6%89%A3%0A%3E%20-%20%E5%90%8C%E4%B8%80%E8%AE%A2%E5%8D%95%E4%B8%AD%EF%BC%8C%E5%8D%95%E4%B8%AA%E5%95%86%E5%93%81%E7%9A%84%E6%95%B0%E9%87%8F%E8%BE%BE%E5%88%B020%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%EF%BC%8C%E4%BA%AB10%25%E7%9A%84%E6%8A%98%E6%89%A3%0A%3E%20-%20%E8%AE%A2%E5%8D%95%E4%B8%AD%E7%9A%84%E4%B8%8D%E5%90%8C%E5%95%86%E5%93%81%E8%BE%BE%E5%88%B010%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%EF%BC%8C%E4%BA%AB7%25%E6%8A%98%E6%89%A3%0A%0A%0A%60%60%60python%0Afrom%20abc%20import%20ABC%20%2C%20abstracmethod%0Afrom%20collections%20import%20namdtuple%0A%0ACustomer%20%3D%20namdtuple('Customer'%2C'name%20fidelity')%20%20%20%20%23%E5%AE%A2%E6%88%B7%E5%90%8Dname%20%E5%92%8C%E7%A7%AF%E5%88%86%E6%95%B0fidelity%20%20%20namdtuple%E8%BF%98%E8%A6%81%E8%AE%B0%E5%BE%97%E5%85%88%E4%BC%A0%E5%85%A5%E7%B1%BB%E5%90%8D%0A%0Aclass%20LineItem%3A%20%20%20%20%23%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E7%B1%BB%0A%20%20%20%20def%20__init__(self%20%2C%20product%20%2C%20quantity%20%2C%20price)%3A%0A%20%20%20%20%20%20%20%20self.product%20%3D%20product%20%20%20%23%E5%85%B7%E4%BD%93%E5%95%86%E5%93%81%0A%20%20%20%20%20%20%20%20self.quantity%20%3D%20quantity%20%20%20%23%E6%95%B0%E9%87%8F%0A%20%20%20%20%20%20%20%20self.price%20%3D%20price%20%20%20%20%20%20%20%20%20%20%20%20%20%23%E5%8D%95%E4%BB%B7%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20def%20total(self)%3A%20%20%20%20%20%23%E6%80%BB%E4%BB%B7%0A%20%20%20%20%20%20%20%20return%20self.price%20*%20self.quantity%0A%20%20%20%20%20%20%20%20%0Aclass%20Order%3A%20%20%20%23%E4%B8%8A%E4%B8%8B%E6%96%87%0A%20%20%20%20%0A%20%20%20%20def%20__init__(self%20%2C%20customer%20%2C%20cart%20%2C%20promotion%20%3D%20None)%3A%20%20%20%0A%20%20%20%20%20%20%20%20self.customer%20%3D%20customer%20%20%20%23%E5%AE%A2%E6%88%B7%E7%B1%BB%0A%20%20%20%20%20%20%20%20self.cart%20%3D%20list(cart)%20%20%20%20%20%20%20%20%20%23%E7%94%B1%E5%85%B7%E4%BD%93%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E7%BB%84%E6%88%90%E7%9A%84%E5%88%97%E8%A1%A8%0A%20%20%20%20%20%20%20%20self.promotion%20%3D%20promotion%20%20%20%20%23%E5%85%B7%E4%BD%93%E7%9A%84%E6%89%93%E6%8A%98%E7%AD%96%E7%95%A5%0A%20%20%20%20%0A%20%20%20%20def%20total(self)%3A%0A%20%20%20%20%20%20%20%20if%20not%20hasattr(self%20%2C%20'__total')%3A%20%20%20%20%23%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E6%9C%89__total%E8%BF%99%E4%B8%AA%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20%20%20%20%20%20self.__total%20%3D%20sum(item.total()%20for%20item%20in%20self.cart)%0A%20%20%20%20%20%20%20%20return%20self.__total%0A%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20def%20due(self)%3A%0A%20%20%20%20%20%20%20%20if%20self.promotion%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20discount%20%3D%200%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20discount%20%3D%20self.promotion.discount(self)%0A%20%20%20%20%20%20%20%20return%20self.total()%20-%20discount%0A%20%20%20%20%0A%20%20%20%20def%20__repr__(self)%3A%0A%20%20%20%20%20%20%20%20fmt%20%3D%20'%3COrder%20total%20%3A%20%7B%20%3A%20.2f%20%7D%20due%20%3A%20%7B%20%3A%20.2f%20%7D%3E'%0A%20%20%20%20%20%20%20%20return%20fmt.format(self.total()%20%2C%20self.due())%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0Aclass%20Promotion(ABC)%3A%20%20%20%23%E7%AD%96%E7%95%A5%EF%BC%8C%E6%8A%BD%E8%B1%A1%E5%9F%BA%E7%B1%BB%0A%20%20%20%20%40abstractmothod%0A%20%20%20%20def%20discount(self%20%2C%20other)%3A%0A%20%20%20%20%20%20%20%20'''%E8%BF%94%E5%9B%9E%E6%8A%98%E6%89%A3%E9%87%91%E9%A2%9D%EF%BC%88%E6%AD%A3%E5%80%BC%EF%BC%89'''%20%20%20%20%20%20%23%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AA%E6%9C%89%E6%96%B9%E6%B3%95%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%EF%BC%8C%E4%B8%93%E9%97%A8%E8%AE%BE%E8%AE%A1%E4%B8%BA%E6%9D%A5%E8%A2%AB%E7%BB%A7%E6%89%BF%E7%9A%84%0A%0Aclass%20FidelityPromo(Promotion)%3A%20%23%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%AD%96%E7%95%A5%20%20%E9%83%BD%E6%98%AFPromotion%E7%9A%84%E5%AD%90%E7%B1%BB%0A%20%20%20%20'''%E4%B8%BA%E7%A7%AF%E5%88%86%E4%B8%BA1000%E6%88%96%E4%BB%A5%E4%B8%8A%E7%9A%84%E9%A1%BE%E5%AE%A2%E6%8F%90%E4%BE%9B5%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20%0A%20%20%20%20def%20discount(self%20.%20other)%3A%20%20%20%23%E7%BB%A7%E6%89%BF%E5%90%8E%E8%A6%86%E5%86%99%EF%BC%8C%E5%AE%8C%E6%88%90%E5%85%B7%E4%BD%93%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0%0A%20%20%20%20%20%20%20%20return%20order.total()%20*%20.05%20if%20order.customer.fidelity%20%3E%3D%201000%20else%200%0A%20%0A%20%0A%20class%20BulkItemPromo(Promotion)%3A%20%20%23%E7%AC%AC%E4%BA%8C%E4%B8%AA%E7%AD%96%E7%95%A5%0A%20%20%20%20'''%E5%8D%95%E4%B8%AA%E5%95%86%E5%93%81%E4%B8%BA20%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%E6%97%B6%E6%8F%90%E4%BE%9B10%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20def%20discount(self%20%2C%20other%20)%3A%0A%20%20%20%20%20%20%20%20discount%20%3D%200%0A%20%20%20%20%20%20%20%20for%20item%20in%20order.cart%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20item.quantity%20%3E%3D%2020%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20discount%20%2B%3D%20item.total()%20*%20.1%0A%20%20%20%20%20%20%20%20return%20discount%0A%20%0A%20class%20LargeOrderPromo(Promotion)%3A%20%20%23%E7%AC%AC%E4%B8%89%E4%B8%AA%E7%AD%96%E7%95%A5%0A%20%20%20%20'''%E8%AE%A2%E5%8D%95%E4%B8%AD%E7%9A%84%E4%B8%8D%E5%90%8C%E5%95%86%E5%93%81%E8%BE%BE%E5%88%B010%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%E6%97%B6%E6%8F%90%E4%BE%9B7%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20def%20discount(self%2C%20order)%3A%0A%20%20%20%20%20%20%20%20distinct_items%20%3D%20%7Bitem.product%20for%20item%20in%20order.cart%7D%0A%20%20%20%20%20%20%20%20if%20len(distinct_items)%20%3E%3D%2010%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20order.total()%20*%20.07%0A%20%20%20%20%20%20%20%20return%200%0A%20%20%20%20%0A%60%60%60%0A%0A%60%60%60python%0Ajoe%20%3D%20Customer('John%20doe'%20%2C%200)%0Aann%20%3D%20Customer('Ann%20Smith'%20%2C%201100%20)%0Acart%20%3D%20%5BLineItem('banana'%2C%204%2C%20.5)%2C%0A%20%20%20%20%20%20%20%20%20%20LineItem('Apple'%20%2C%2010%20%2C%201.5)%2C%0A%20%20%20%20%20%20%20%20%20%20LineItem('watermellon'%2C%205%2C%205.0)%5D%0AOrder(joe%2C%20cart%20%2C%20FidelityPromo()%20)%20%20%20%20%20%20%23%20%3COrder%20total%20%3A%2042.00%20due%20%3A%2042.00%3E%0AOrder(ann%20%2C%20cart%20%2C%20FidelityPromo()%20)%20%20%20%20%20%20%23%20%3COrder%20total%20%3A%2042.00%20due%20%3A%2039.00%3E%0A%0A%60%60%60%0A%0A%23%23%23%23%20%E4%BD%BF%E7%94%A8%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E2%80%9C%E7%AD%96%E7%95%A5%E2%80%9D%E6%A8%A1%E5%BC%8F%0A%60%60%60python%0Afrom%20abc%20import%20ABC%20%2C%20abstracmethod%0Afrom%20collections%20import%20namdtuple%0A%0ACustomer%20%3D%20namdtuple('Customer'%2C'name%20fidelity')%20%20%20%20%23%E5%AE%A2%E6%88%B7%E5%90%8Dname%20%E5%92%8C%E7%A7%AF%E5%88%86%E6%95%B0fidelity%20%20%20namdtuple%E8%BF%98%E8%A6%81%E8%AE%B0%E5%BE%97%E5%85%88%E4%BC%A0%E5%85%A5%E7%B1%BB%E5%90%8D%0A%0Aclass%20LineItem%3A%20%20%20%20%23%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E7%B1%BB%0A%20%20%20%20def%20__init__(self%20%2C%20product%20%2C%20quantity%20%2C%20price)%3A%0A%20%20%20%20%20%20%20%20self.product%20%3D%20product%20%20%20%23%E5%85%B7%E4%BD%93%E5%95%86%E5%93%81%0A%20%20%20%20%20%20%20%20self.quantity%20%3D%20quantity%20%20%20%23%E6%95%B0%E9%87%8F%0A%20%20%20%20%20%20%20%20self.price%20%3D%20price%20%20%20%20%20%20%20%20%20%20%20%20%20%23%E5%8D%95%E4%BB%B7%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20def%20total(self)%3A%20%20%20%20%20%23%E6%80%BB%E4%BB%B7%0A%20%20%20%20%20%20%20%20return%20self.price%20*%20self.quantity%0A%20%20%20%20%20%20%20%20%0Aclass%20Order%3A%20%20%20%23%E4%B8%8A%E4%B8%8B%E6%96%87%0A%20%20%20%20%0A%20%20%20%20def%20__init__(self%20%2C%20customer%20%2C%20cart%20%2C%20promotion%20%3D%20None)%3A%20%20%20%0A%20%20%20%20%20%20%20%20self.customer%20%3D%20customer%20%20%20%23%E5%AE%A2%E6%88%B7%E7%B1%BB%0A%20%20%20%20%20%20%20%20self.cart%20%3D%20list(cart)%20%20%20%20%20%20%20%20%20%23%E7%94%B1%E5%85%B7%E4%BD%93%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E7%BB%84%E6%88%90%E7%9A%84%E5%88%97%E8%A1%A8%0A%20%20%20%20%20%20%20%20self.promotion%20%3D%20promotion%20%20%20%20%23%E5%85%B7%E4%BD%93%E7%9A%84%E6%89%93%E6%8A%98%E7%AD%96%E7%95%A5%0A%20%20%20%20%0A%20%20%20%20def%20total(self)%3A%0A%20%20%20%20%20%20%20%20if%20not%20hasattr(self%20%2C%20'__total')%3A%20%20%20%20%23%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E6%9C%89__total%E8%BF%99%E4%B8%AA%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20%20%20%20%20%20self.__total%20%3D%20sum(item.total()%20for%20item%20in%20self.cart)%0A%20%20%20%20%20%20%20%20return%20self.__total%0A%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20def%20due(self)%3A%0A%20%20%20%20%20%20%20%20if%20self.promotion%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20discount%20%3D%200%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%E5%B7%AE%E5%88%AB%20%20%E9%87%8D%E7%82%B9%0A%20%20%20%20%20%20%20%20%20%20%20%20discount%20%3D%20self.promotion(self)%20%20%20%20%20%23%E8%B0%83%E7%94%A8self.promotion%E5%87%BD%E6%95%B0%20%EF%BC%8C%20%E4%BC%A0%E5%85%A5%E5%BD%93%E5%89%8D%E5%AE%9E%E4%BE%8B%2C%20%20self.%3C%3E(self)%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20return%20self.total()%20-%20discount%0A%20%20%20%20%0A%20%20%20%20def%20__repr__(self)%3A%0A%20%20%20%20%20%20%20%20fmt%20%3D%20'%3COrder%20total%20%3A%20%7B%20%3A%20.2f%20%7D%20due%20%3A%20%7B%20%3A%20.2f%20%7D%3E'%0A%20%20%20%20%20%20%20%20return%20fmt.format(self.total()%20%2C%20self.due())%0A%20%20%20%20%20%20%20%20%0A%23%E4%B8%8D%E7%94%A8%E6%8A%BD%E8%B1%A1%E7%B1%BB%E4%BA%86%0Adef%20fidelityPromo(order)%3A%20%23%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%AD%96%E7%95%A5%20%20%0A%20%20%20%20'''%E4%B8%BA%E7%A7%AF%E5%88%86%E4%B8%BA1000%E6%88%96%E4%BB%A5%E4%B8%8A%E7%9A%84%E9%A1%BE%E5%AE%A2%E6%8F%90%E4%BE%9B5%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20return%20order.total()%20*%20.05%20if%20order.customer.fidelity%20%3E%3D%201000%20else%200%0A%20%0A%20%0Adef%20bulkItemPromo(order)%3A%20%20%23%E7%AC%AC%E4%BA%8C%E4%B8%AA%E7%AD%96%E7%95%A5%0A%20%20%20%20'''%E5%8D%95%E4%B8%AA%E5%95%86%E5%93%81%E4%B8%BA20%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%E6%97%B6%E6%8F%90%E4%BE%9B10%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20%20%20%20%20discount%20%3D%200%0A%20%20%20%20%20%20%20%20for%20item%20in%20order.cart%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20item.quantity%20%3E%3D%2020%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20discount%20%2B%3D%20item.total()%20*%20.1%0A%20%20%20%20%20%20%20%20return%20discount%0A%20%0A%20def%20largeOrderPromo(order)%3A%20%20%23%E7%AC%AC%E4%B8%89%E4%B8%AA%E7%AD%96%E7%95%A5%0A%20%20%20%20'''%E8%AE%A2%E5%8D%95%E4%B8%AD%E7%9A%84%E4%B8%8D%E5%90%8C%E5%95%86%E5%93%81%E8%BE%BE%E5%88%B010%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%E6%97%B6%E6%8F%90%E4%BE%9B7%25%E7%9A%84%E6%8A%98%E6%89%A3'''%0A%20%20%20%20%20%20%20%20distinct_items%20%3D%20%7Bitem.product%20for%20item%20in%20order.cart%7D%0A%20%20%20%20%20%20%20%20if%20len(distinct_items)%20%3E%3D%2010%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20order.total()%20*%20.07%0A%20%20%20%20%20%20%20%20return%200%0A%60%60%60%0A%0A%0A%3E%20__%E7%AD%96%E7%95%A5%E5%AF%B9%E8%B1%A1%E9%80%9A%E5%B8%B8%E6%98%AF%E5%BE%88%E5%A5%BD%E7%9A%84%E4%BA%AB%E5%85%83%EF%BC%88%E5%8F%AF%E5%85%B1%E4%BA%AB%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E5%9C%A8%E5%A4%9A%E4%B8%AA%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%85%B1%E4%BA%AB%E6%98%AF%E6%8E%A8%E8%8D%90%E7%9A%84%E5%81%9A%E6%B3%95%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%8F%AF%E4%BB%A5%E4%B8%8D%E7%94%A8%E5%86%8D%E6%AF%8F%E4%B8%AA%E6%96%B0%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9B%B8%E5%90%8C%E7%9A%84%E7%AD%96%E7%95%A5%E6%97%B6%E4%B8%8D%E6%96%AD%E6%96%B0%E5%BB%BA%E5%85%B7%E4%BD%93%E7%AD%96%E7%95%A5%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%87%8F%E5%B0%91%E6%B6%88%E8%80%97%EF%BC%89%E3%80%82__%0A%3E%20__%E5%85%B7%E4%BD%93%E7%AD%96%E7%95%A5%E4%B8%80%E8%88%AC%E6%B2%A1%E6%9C%89%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%EF%BC%8C%E5%8F%AA%E6%98%AF%E5%A4%84%E7%90%86%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%89%80%E4%BB%A5%E5%A4%8D%E6%9D%82%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%B8%80%E5%AE%9A%E8%A6%81%E7%94%A8%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E2%80%9C%E7%AD%96%E7%95%A5%E2%80%9D%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%87%BD%E6%95%B0%E6%AF%94%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E7%9A%84%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%E6%9B%B4%E8%BD%BB%E9%87%8F%EF%BC%8C%E8%80%8C%E4%B8%94%E6%97%A0%E9%9C%80%E4%BD%BF%E7%94%A8%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%90%84%E4%B8%AA%E7%AD%96%E7%95%A5%E5%87%BD%E6%95%B0%E5%9C%A8Python%E7%BC%96%E8%AF%91%E6%A8%A1%E5%9D%97%E6%97%B6%E5%8F%AA%E4%BC%9A%E5%88%9B%E5%BB%BA%E4%B8%80%E6%AC%A1%E3%80%82%E6%99%AE%E9%80%9A%E7%9A%84%E5%87%BD%E6%95%B0%E4%B9%9F%E6%98%AF%E2%80%9C%E5%8F%AF%E5%85%B1%E4%BA%AB%E7%9A%84%E5%AF%B9%E8%B1%A1%E2%80%9D%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E5%9C%A8%E5%A4%9A%E4%B8%AA%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%BD%BF%E7%94%A8%E3%80%82__%0A%0A%0A%0A%23%23%23%23%20%E9%80%89%E6%8B%A9%E6%9C%80%E4%BD%B3%E7%AD%96%E7%95%A5%EF%BC%9A%E7%AE%80%E5%8D%95%E7%9A%84%E6%96%B9%E5%BC%8F%0A%60%60%60python%0Apromos%20%3D%20%5Bfidelity_promo%20%2C%20bulk_item_promo%20%2C%20large_oder_promo%5D%0A%0Adef%20best_promo(order)%3A%0A%20%20%20%20'''%0A%20%20%20%20%20%20%20%20%E4%BD%BF%E7%94%A8%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%8A%8Aorder%E4%BC%A0%E7%BB%99promos%E5%88%97%E8%A1%A8%E4%B8%AD%E7%9A%84%E5%90%84%E4%B8%AA%E5%87%BD%E6%95%B0%EF%BC%8C%E8%BF%94%E5%9B%9E%E6%8A%98%E6%89%A3%E9%A2%9D%E5%BA%A6%E6%9C%80%E5%A4%A7%E7%9A%84%E9%82%A3%E4%B8%AA%E5%87%BD%E6%95%B0%0A%20%20%20%20'''%0A%20%20%20%20return%20max(promo(order)%20for%20promo%20in%20promos)%20%20%20%20%20%20%20%0A%20%20%20%20%0A%60%60%60%0A__%E4%B8%8D%E8%B6%B3%EF%BC%9A%E5%A6%82%E6%9E%9C%E6%B7%BB%E5%8A%A0%E4%BA%86%E6%96%B0%E7%9A%84%E9%94%80%E5%94%AE%E7%AD%96%E7%95%A5%EF%BC%8C%E8%A6%81%E5%AE%9A%E4%B9%89%E7%9B%B8%E5%BA%94%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%8C%E8%BF%98%E5%BE%97%E8%AE%B0%E5%BE%97%E6%8A%8A%E6%96%B0%E5%87%BD%E6%95%B0%E6%B7%BB%E5%8A%A0%E5%88%B0promos%E4%B8%AD%EF%BC%8C%E5%90%A6%E5%88%99best_promos%E4%B8%8D%E4%BC%9A%E8%80%83%E8%99%91%E5%AE%83__%0A%0A__%E6%94%B9%E8%BF%9B%EF%BC%9A%E4%BD%BF%E7%94%A8%E5%A4%84%E7%90%86%E6%A8%A1%E5%9D%97%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%8C%E6%89%BE%E5%87%BA%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84%E5%85%A8%E9%83%A8%E7%AD%96%E7%95%A5__%0A%3E%20globals()%20%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%AD%97%E5%85%B8%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%BD%93%E5%89%8D%E7%9A%84%E5%85%A8%E5%B1%80%E7%AC%A6%E5%8F%B7%E8%A1%A8%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%AC%A6%E5%8F%B7%E8%A1%A8%E5%A7%8B%E7%BB%88%E9%92%88%E5%AF%B9%E5%BD%93%E5%89%8D%E6%A8%A1%E5%9D%97%0A%0A%60%60%60python%0A%20%20%20%20promos%20%3D%20%5Bglobals()%5Bname%5D%20for%20name%20in%20globals()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20name.endwith('_promo')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20name%20!%3D%20'best_promo'%5D%0A%20%20%20%20def%20best_promo(order)%3A%0A%20%20%20%20%20%20%20%20%20return%20max(promo(order)%20for%20promo%20in%20promos)%0A%20%20%20%20%0A%60%60%60%0A%23%23%23%20%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F%0A-%20%E7%95%A5%0A%0A%0A%23%23%23%23%23%20%E7%94%A8%E8%A3%85%E9%A5%B0%E5%99%A8%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%A7%A3%E5%86%B3%E7%94%B5%E5%95%86%E9%97%AE%E9%A2%98%EF%BC%8C%E6%9C%AA%E5%AE%8C%E5%BE%85%E7%BB%AD%0A%0A%0A%0A%0A%0A%0A</center></span>
</div></body></html> 